'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');

var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _checkbox = require('antd/lib/checkbox');

var _checkbox2 = _interopRequireDefault(_checkbox);

var _row = require('antd/lib/row');

var _row2 = _interopRequireDefault(_row);

var _col = require('antd/lib/col');

var _col2 = _interopRequireDefault(_col);

var _input = require('antd/lib/input');

var _input2 = _interopRequireDefault(_input);

var _radio = require('antd/lib/radio');

var _radio2 = _interopRequireDefault(_radio);

var _select = require('antd/lib/select');

var _select2 = _interopRequireDefault(_select);

var _reactLifecyclesCompat = require('react-lifecycles-compat');

var _Icon = require('./Icon');

var _Icon2 = _interopRequireDefault(_Icon);

var _Color = require('./Color');

var _Color2 = _interopRequireDefault(_Color);

var _RowHelp = require('./RowHelp');

var _RowHelp2 = _interopRequireDefault(_RowHelp);

var _SelectInput = require('./SelectInput');

var _SelectInput2 = _interopRequireDefault(_SelectInput);

var _utils = require('../../utils');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var Option = _select2['default'].Option;

var InputGroup = _input2['default'].Group;
var RadioButton = _radio2['default'].Button;
var RadioGroup = _radio2['default'].Group;

var GradientEdit = function (_React$Component) {
  (0, _inherits3['default'])(GradientEdit, _React$Component);
  (0, _createClass3['default'])(GradientEdit, null, [{
    key: 'getDerivedStateFromProps',
    value: function getDerivedStateFromProps(props, _ref) {
      var prevProps = _ref.prevProps,
          $self = _ref.$self;

      var nextState = {
        prevProps: props
      };
      if (prevProps && prevProps.type !== props.type) {
        $self.percentRef.state.value = 0;
        nextState = (0, _extends3['default'])({}, nextState, $self.getGradientData(props), {
          active: 0
        });
      }
      return nextState;
    }
  }]);

  function GradientEdit(props) {
    (0, _classCallCheck3['default'])(this, GradientEdit);

    var _this = (0, _possibleConstructorReturn3['default'])(this, (GradientEdit.__proto__ || Object.getPrototypeOf(GradientEdit)).call(this, props));

    _initialiseProps.call(_this);

    _this.pos = {};

    _this.shape = ['circle', 'ellipse'];

    _this.extent = ['farthest-corner', 'farthest-side', 'closest-corner', 'closest-side'];

    _this.position = ['center', 'center left', 'center right', 'top', 'top left', 'top right', 'bottom', 'bottom left', 'bottom right'];
    _this.state = (0, _extends3['default'])({}, _this.getGradientData(props), {
      active: 0,
      $self: _this
    });
    return _this;
  }

  (0, _createClass3['default'])(GradientEdit, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      window.addEventListener('mousemove', this.onPointMove);
      window.addEventListener('mouseup', this.onPointUp);
    }
  }, {
    key: 'render',
    value: function render() {
      var _this2 = this;

      var _props = this.props,
          className = _props.className,
          locale = _props.locale;
      var _state = this.state,
          active = _state.active,
          gradient = _state.gradient,
          repeat = _state.repeat;


      var point = gradient.map(function (item, i) {
        var left = item[1];
        left = parseFloat(left) > 100 ? '100%' : left;
        left = parseFloat(left) < 0 ? '0%' : left;
        var classNames = (0, _classnames2['default'])(className + '-point', {
          active: active === i
        });
        var style = {
          left: left
        };
        if (active === i) {
          style.backgroundColor = item[0];
        }
        return _react2['default'].createElement('div', {
          className: classNames,
          style: style,
          key: i.toString(),
          onClick: function onClick(e) {
            if (e.stopPropagation) {
              e.stopPropagation();
            } else {
              e.cancelBubble = true;
            }
          },
          onMouseDown: function onMouseDown(e) {
            _this2.onPointClick(e, i);
          },
          onMouseUp: _this2.onPointUp,
          onContextMenu: _this2.onPointUp
        });
      });
      var value = gradient[active];
      var featChild = this.getFeatChildToRender();
      return _react2['default'].createElement(
        'div',
        { className: className },
        _react2['default'].createElement(
          _row2['default'],
          { gutter: 8, key: 'repeat', className: className + '-color' },
          _react2['default'].createElement(
            _col2['default'],
            { span: 21 },
            _react2['default'].createElement(
              _checkbox2['default'],
              { onChange: this.onRepeatChange, checked: repeat },
              locale.repeatGradient
            )
          ),
          _react2['default'].createElement(
            _col2['default'],
            { span: 3 },
            _react2['default'].createElement(_Icon2['default'], { type: 'question-circle', prompt: locale.barHelp })
          )
        ),
        _react2['default'].createElement(
          'div',
          {
            className: className + '-bar',
            style: {
              backgroundImage: 'linear-gradient(to right, ' + gradient.map(function (item) {
                return item.join(' ');
              }).join(',') + '), url(' + _utils.alphaBg + ')'
            },
            onClick: this.onBarClick,
            ref: function ref(c) {
              _this2.bar = c;
            }
          },
          _react2['default'].createElement(
            'div',
            { className: className + '-bar-item' },
            point
          )
        ),
        _react2['default'].createElement(
          _row2['default'],
          { gutter: 8, key: 'color', className: className + '-color' },
          _react2['default'].createElement(
            _col2['default'],
            { span: 16, gutter: 0 },
            _react2['default'].createElement(_Color2['default'], {
              span: [5, 7, 12],
              title: _react2['default'].createElement(_Icon2['default'], { type: 'bg-colors', prompt: locale.color }),
              color: _utils.colorLookup[value[0]] || value[0],
              onChange: function onChange(e, isDrag) {
                _this2.onColorChange(e, isDrag);
              }
            })
          ),
          _react2['default'].createElement(
            _col2['default'],
            { span: 8 },
            _react2['default'].createElement(_input2['default'], {
              defaultValue: parseFloat(value[1] || ''),
              ref: function ref(c) {
                _this2.percentRef = c;
              },
              size: 'small',
              addonAfter: '%',
              onChange: this.onPercentChange,
              onBlur: this.onPercentBlur,
              onPressEnter: this.onPercentPressEnter
            })
          )
        ),
        featChild
      );
    }
  }]);
  return GradientEdit;
}(_react2['default'].Component);

GradientEdit.propTypes = {
  className: _propTypes2['default'].string,
  locale: _propTypes2['default'].object,
  value: _propTypes2['default'].any,
  onChange: _propTypes2['default'].func,
  num: _propTypes2['default'].number,
  type: _propTypes2['default'].string
};
GradientEdit.defaultProps = {
  className: 'editor-gradient'
};

var _initialiseProps = function _initialiseProps() {
  var _this3 = this;

  this.onBarClick = function (e) {
    var gradient = _this3.state.gradient;

    var rect = _this3.bar.getBoundingClientRect();
    var x = e.clientX || e.pageX;
    var currentPercent = ((x - rect.x) / rect.width * 100).toFixed(2);
    var current = ['black', currentPercent + '%'];
    // const index = gradient.filter(c => (parseFloat(c[1])) < currentPercent).length - 1;
    // gradient.splice(index, 0, current);
    gradient.push(current);
    gradient.sort(function (a, b) {
      return parseFloat(a[1]) - parseFloat(b[1]);
    });
    _this3.setState({
      gradient: gradient,
      active: gradient.findIndex(function (c) {
        return c === current;
      })
    }, _this3.onChange);
  };

  this.onPointClick = function (e, i) {
    _this3.setState({
      active: i
    });
    var gradient = _this3.state.gradient;

    _this3.isDrag = true;
    _this3.current = gradient[i][1];
    _this3.pos = {
      x: e.clientX || e.pageX,
      y: e.clientY || e.pageY
    };
    _this3.barRect = _this3.bar.getBoundingClientRect();
    _this3.percentRef.state.value = parseFloat(_this3.current) || (i ? 100 : 0);
  };

  this.onPointUp = function (e) {
    if (_this3.isDrag) {
      var _state2 = _this3.state,
          active = _state2.active,
          gradient = _state2.gradient;

      var y = e.clientY || e.pageY;
      var differ = Math.abs(y - _this3.pos.y);
      if (differ > 40 && gradient.length > 2) {
        gradient.splice(active, 1);
        _this3.setState({
          active: 0,
          gradient: gradient
        }, _this3.onChange);
      }
      _this3.isDrag = false;
      _this3.pos = {};
      _this3.onChange();
    }
  };

  this.onPointMove = function (e) {
    if (_this3.isDrag) {
      var _state3 = _this3.state,
          i = _state3.active,
          g = _state3.gradient;

      var gradient = [].concat((0, _toConsumableArray3['default'])(g));
      var x = e.clientX || e.pageX;
      var rect = _this3.barRect; // this.bar.getBoundingClientRect();
      var w = rect.width - 8;
      // 只支持百分比，不对 px 做处理；
      var p = _this3.current ? parseFloat(_this3.current) / 100 : 0;
      p = p > 1 ? 1 : p;
      p = p < 0 ? 0 : p;
      var differ = x - _this3.pos.x + p * w;
      differ = differ / w * 100;

      differ = differ > 100 ? 100 : differ;
      differ = differ < 0 ? 0 : differ;
      var str = i ? '100%' : '0%';
      gradient[i][1] = differ ? differ + '%' : str;
      var gradientCurrent = gradient[i];
      gradient.sort(function (a, b) {
        return parseFloat(a[1]) - parseFloat(b[1]);
      });
      var active = gradient.findIndex(function (t) {
        return t === gradientCurrent;
      });
      // 控制 ref 里的 state，在下一次 render 时更新 defaultValue 的值；
      _this3.percentRef.state.value = differ || parseFloat(str);
      _this3.active = active;
      _this3.setState({
        gradient: gradient,
        active: active
      }, function () {
        _this3.onChange(true);
      });
    }
  };

  this.onPercentChange = function () {
    _this3.isPressEnter = false;
  };

  this.onPercentBlur = function (e) {
    if (!_this3.isPressEnter) {
      var v = e.target.value.replace(/[^0-9.-]/g, '');
      var _state4 = _this3.state,
          active = _state4.active,
          gradient = _state4.gradient;


      gradient[active][1] = (v || 0) + '%';
      _this3.percentRef.state.value = v || 0;
      _this3.setState({
        gradient: gradient
      }, _this3.onChange);
    }
  };

  this.onPercentPressEnter = function (e) {
    _this3.onPercentBlur(e);
    _this3.isPressEnter = true;
  };

  this.onColorChange = function (e, isDrag) {
    var _state5 = _this3.state,
        active = _state5.active,
        gradient = _state5.gradient;

    gradient[active][0] = e;
    _this3.setState({
      gradient: gradient
    }, function () {
      _this3.onChange(isDrag);
    });
  };

  this.onRepeatChange = function (e) {
    _this3.setState({
      repeat: e.target.checked
    }, _this3.onChange);
  };

  this.onChangeType = function (key, v) {
    var contentType = _this3.state.type;
    var type = _this3.props.type;

    if (type === 'linear') {
      var _getLinearFeat = _this3.getLinearFeat(contentType),
          value = _getLinearFeat.value,
          uint = _getLinearFeat.uint;

      switch (key) {
        case 'deg':
          value = _utils.linearGradientToDeg[v] || _utils.linearGradientToDeg[v] === 0 ? _utils.linearGradientToDeg[v] : v || 0;
          break;
        case 'uint':
          uint = v || 'deg';
          break;
        default:
          break;
      }
      contentType = ('' + value + (value || value === 0 ? uint || 'deg' : '')).trim();
    } else {
      var _getRadialFeat = _this3.getRadialFeat(contentType),
          shape = _getRadialFeat.shape,
          extent = _getRadialFeat.extent,
          position = _getRadialFeat.position;

      switch (key) {
        case 'shape':
          shape = v === _this3.shape[0] ? '' : v;
          break;
        case 'extent':
          extent = v === _this3.extent[0] ? '' : v;
          break;
        case 'position':
          position = v === 'center' ? '' : v;
          break;
        default:
          break;
      }
      contentType = (shape + ' ' + extent + ' ' + (position ? 'at' : '') + ' ' + position).trim();
    }
    _this3.setState({
      type: contentType
    }, _this3.onChange);
  };

  this.onChange = function (isDrag) {
    var _props2 = _this3.props,
        type = _props2.type,
        value = _props2.value,
        num = _props2.num,
        onChange = _props2.onChange;
    var _state6 = _this3.state,
        contentType = _state6.type,
        gradient = _state6.gradient,
        repeat = _state6.repeat;

    var name = '' + (repeat ? 'repeating-' : '') + type + '-gradient';
    var gradientStr = name + '(' + (contentType ? contentType + ', ' : '') + gradient.map(function (c) {
      return c.join(' ');
    }).join(',') + ')';
    value.image[num] = gradientStr;
    if (onChange) {
      onChange(value, isDrag);
    }
  };

  this.getGradientData = function (props) {
    var value = props.value,
        num = props.num;

    var gradientArray = _this3.getGradientArray(props);
    var isRadial = gradientArray[0].match(/at|circle|ellipse/);
    var isLinear = gradientArray[0].match(/deg|turn|rad|grad|to\s+[a-z]/g);
    var type = isRadial || isLinear ? gradientArray.shift() : '';
    var gradient = gradientArray.map(function (str, i) {
      var $str = str.replace(_utils.colorExp, function (e) {
        return e.replace(/\s+/g, '');
      });
      var item = $str.split(' ');
      if (!item[1]) {
        if (!i) {
          item[1] = '0%';
        } else if (i === gradientArray.length - 1) {
          item[1] = '100%';
        } else {
          console.error('gradient error: ' + props.value.image[props.num]);
        }
      }
      var uint = item[1].replace(/[\d+.-]/g, '');
      if (uint !== '%') {
        item[1] = (0, _utils.unitToPercent)(props.editorElem, item[1], uint);
      }
      return item;
    });
    return {
      type: type,
      gradient: gradient,
      repeat: !!value.image[num].match(/^repeating/)
    };
  };

  this.getRadialFeat = function (contentType) {
    var typeArray = contentType.split(' at ');
    var shapeOrExtent = typeArray[0].split(' ');
    var shape = _this3.shape.indexOf(shapeOrExtent[0]) >= 0 ? shapeOrExtent[0] : '';
    var extent = shapeOrExtent[1] && _this3.extent.indexOf(shapeOrExtent[1]) >= 0 ? shapeOrExtent[1] : '';
    extent = shapeOrExtent[0] && _this3.extent.indexOf(shapeOrExtent[0]) >= 0 ? shapeOrExtent[0] : extent;
    var position = typeArray[1] || '';
    return {
      shape: shape,
      extent: extent,
      position: position
    };
  };

  this.getLinearFeat = function (contentType) {
    var str = contentType.match(/deg|turn|rad|grad/) ? contentType : _utils.linearGradientToDeg[contentType] || '';
    var value = parseFloat(str) || parseFloat(str) === 0 ? parseFloat(str) : '';
    var uint = str.toString().replace(/[^a-z]/ig, '');
    if (uint === 'turn') {
      console.warn('不支持 turn 为单位，自动转换为 deg');
      uint = 'deg';
    }
    return {
      value: value,
      uint: uint
    };
  };

  this.getGradientArray = function (_ref2) {
    var value = _ref2.value,
        num = _ref2.num;
    return value.image[num].replace(/.*gradient\((.*)\)/, '$1').split(/,\s?(?=[a-z#])/g);
  };

  this.getFeatChildToRender = function () {
    /**
     * 圆形渐变
     * (shape extent-keyword at position, color)
     * 线性渐变
     * (side-or-corner || angle, color position) // 颜色后面只支持一个位置百分比; 只支持渐变的效果，画栅格可以加点。
     */
    var _props3 = _this3.props,
        type = _props3.type,
        className = _props3.className,
        locale = _props3.locale;
    var contentType = _this3.state.type;

    if (type === 'linear') {
      var _getLinearFeat2 = _this3.getLinearFeat(contentType),
          uint = _getLinearFeat2.uint,
          value = _getLinearFeat2.value;

      return _react2['default'].createElement(
        'div',
        { className: className + '-feat' },
        _react2['default'].createElement(
          _RowHelp2['default'],
          {
            title: _react2['default'].createElement(_Icon2['default'], { type: 'reload', prompt: locale.angle }),
            help: locale.angleHelp
          },
          _react2['default'].createElement(
            InputGroup,
            { compact: true },
            _react2['default'].createElement(
              _SelectInput2['default'],
              {
                style: { width: 'calc(100% - 60px)' },
                value: value.toString(),
                size: 'small',
                onChange: function onChange(e) {
                  _this3.onChangeType('deg', e);
                }
              },
              (0, _utils.getOption)(_utils.linearGradientToDeg)
            ),
            _react2['default'].createElement(
              _select2['default'],
              {
                size: 'small',
                value: uint || 'deg',
                style: { width: 60 },
                onChange: function onChange(e) {
                  _this3.onChangeType('uint', e);
                }
              },
              _react2['default'].createElement(
                Option,
                { value: 'deg' },
                'deg'
              ),
              _react2['default'].createElement(
                Option,
                { value: 'rad' },
                'rad'
              ),
              _react2['default'].createElement(
                Option,
                { value: 'grad' },
                'grad'
              )
            )
          )
        )
      );
    }

    var _getRadialFeat2 = _this3.getRadialFeat(contentType),
        shape = _getRadialFeat2.shape,
        extent = _getRadialFeat2.extent,
        position = _getRadialFeat2.position;

    return _react2['default'].createElement(
      'div',
      { className: className + '-feat' },
      _react2['default'].createElement(
        _row2['default'],
        { gutter: 8 },
        _react2['default'].createElement(
          _col2['default'],
          { span: 3 },
          _react2['default'].createElement(_Icon2['default'], { type: 'shape', prompt: locale.shape })
        ),
        _react2['default'].createElement(
          _col2['default'],
          { span: 21 },
          _react2['default'].createElement(
            RadioGroup,
            {
              value: shape || _this3.shape[0],
              size: 'small',
              onChange: function onChange(e) {
                var v = e.target.value;
                _this3.onChangeType('shape', v);
              }
            },
            (0, _utils.getRadioButton)(_this3.shape)
          )
        )
      ),
      _react2['default'].createElement(
        _row2['default'],
        { gutter: 8 },
        _react2['default'].createElement(
          _col2['default'],
          { span: 3 },
          _react2['default'].createElement(_Icon2['default'], { type: 'extent', prompt: locale.extent })
        ),
        _react2['default'].createElement(
          _col2['default'],
          { span: 21 },
          _react2['default'].createElement(
            RadioGroup,
            {
              value: extent || _this3.extent[0],
              size: 'small',
              onChange: function onChange(e) {
                var v = e.target.value;
                _this3.onChangeType('extent', v);
              }
            },
            Object.keys(locale.extentSelect).map(function (key) {
              return _react2['default'].createElement(
                RadioButton,
                { value: key, key: key },
                _react2['default'].createElement(_Icon2['default'], { type: key, prompt: locale.extentSelect[key] })
              );
            })
          )
        )
      ),
      _react2['default'].createElement(
        _RowHelp2['default'],
        {
          title: _react2['default'].createElement(_Icon2['default'], { type: 'imagePosition', prompt: locale.radialPosition }),
          help: locale.position_help
        },
        _react2['default'].createElement(
          _SelectInput2['default'],
          {
            style: { width: '100%' },
            value: position || 'center',
            size: 'small',
            onChange: function onChange(e) {
              _this3.onChangeType('position', e);
            }
          },
          (0, _utils.getOptionArray)(_this3.position)
        )
      )
    );
  };
};

exports['default'] = (0, _reactLifecyclesCompat.polyfill)(GradientEdit);
module.exports = exports['default'];